/*****************************************************
This program was produced by the
CodeWizardAVR V1.24.8d Professional
Automatic Program Generator
 Copyright 1998-2006 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : Propeller Clock
Version : 1.0
Date    : 04.26.2013
Author  : Cahyo Ari Wibowo           
Company : Easy-PCB.com
Comments: 

Chip type           : AT90S2313
Clock frequency     : 12,000000 MHz
Memory model        : Tiny
External SRAM size  : 0
Data Stack size     : 32       

866 words (84.6% of FLASH)
759 words (74,1% of FLASH)    
761 words (74,3% of FLASH)
*****************************************************/

#include <tiny2313.h>   
#include <delay.h>     

unsigned char max_days[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};                        
unsigned char sec, min, hour, month, day_of_week, day_of_month, tmr_cnt, mode;
volatile unsigned char _cmd;
unsigned int ms, day, year;    

#define tmr 250

flash const unsigned char font[11][8] = {
{0x00, 0x00, 0xFE, 0x81, 0x81, 0xFE, 0x00, 0x00},  // 0
{0x00, 0x00, 0x04, 0x02, 0xFF, 0x00, 0x00, 0x00},  // 1
{0x80, 0x40, 0xA2, 0x11, 0x89, 0x06, 0x80, 0x00},  // 2
{0xC0, 0x00, 0x82, 0x01, 0x89, 0x76, 0x00, 0x00},  // 3
{0x00, 0x10, 0x18, 0x14, 0x12, 0xFF, 0x10, 0x00},  // 4
{0x40, 0x8F, 0x09, 0x89, 0x09, 0x90, 0x60, 0x00},  // 5
{0x00, 0xF0, 0x0C, 0x8A, 0x09, 0x90, 0x60, 0x00},  // 6
{0x00, 0x00, 0x01, 0xF1, 0x09, 0x05, 0x03, 0x00},  // 7
{0x60, 0x96, 0x09, 0x89, 0x09, 0x96, 0x60, 0x00},  // 8
{0x00, 0x00, 0x0E, 0x91, 0x51, 0x3E, 0x00, 0x00},  // 9
{0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00}   // :
};   

//8x5 font for down parth screen
flash const unsigned char d_font[12][5] = {
{0x00, 0x1E, 0x21, 0x21, 0x1E},  // 0
{0x00, 0x00, 0x3F, 0x10, 0x08},  // 1
{0x00, 0x19, 0x25, 0x23, 0x11},  // 2
{0x00, 0x16, 0x29, 0x21, 0x12},  // 3
{0x00, 0x3F, 0x04, 0x04, 0x4C},  // 4
{0x00, 0x26, 0x29, 0x29, 0x39},  // 5
{0x00, 0x06, 0x29, 0x29, 0x1E},  // 6
{0x00, 0x30, 0x28, 0x27, 0x20},  // 7
{0x00, 0x16, 0x29, 0x29, 0x16},  // 8
{0x00, 0x18, 0x26, 0x25, 0x18},  // 9                            
{0x00, 0x03, 0x03, 0x00, 0x00},  //.
{0x00, 0x07, 0x06, 0x00, 0x00}  // ,
};    

//********************************************
// External Interrupt 1 service routine 
// Scr for display
//********************************************
interrupt [EXT_INT1] void ext_int1_isr(void)
{
unsigned char i, s, tmp;
char str[10];
tmp = hour/10;
str[0] = tmp;
str[1] = hour-tmp*10;
str[2] = 10;
tmp    = min/10;
str[3] = tmp;
str[4] = min-tmp*10;
str[5] = 10;
tmp    = sec/10;
str[6] = tmp;
str[7] = sec-tmp*10;    
for (s=0; s<8; s++)
    {
    for (i=0; i<7; i++)
        {
        PORTB = font[str[s]][i];
        delay_us(tmr);
        };  
     PORTB = 0;
     delay_us(tmr);   
     };   

for (i=0; i<6; i++)
        delay_us(tmr);

//output data
//year
tmp = year/10;
str[0] = year-tmp*10;
str[1] = tmp-tmp/10*10;
str[2] = 0;
str[3] = 2;
str[4] = 10;
//month   
tmp    = month/10;
str[5] = month-tmp*10;
str[6] = tmp;
str[7] = 10;
//day
tmp    = day_of_month/10;
str[8] = day_of_month-tmp*10;
str[9] = tmp;
for (s=0; s<10; s++)
    {
    for (i=0; i<6; i++)
        {
        PORTB = d_font[str[s]][i];
        delay_us(tmr);
        };  
     PORTB = 0;
     delay_us(tmr);   
     };   
}

//**********************************************************************************
// External Interrupt 0 service routine receive command from IR remote control unit
//**********************************************************************************
interrupt [EXT_INT0] void ext_int0_isr(void)
{unsigned char ppp, pin;
 unsigned int _tmp, tout;
GIMSK = 0;
  _tmp = 1;  

for(ppp = 1; ppp<14; ppp++)
    {delay_us(1200); 
     pin = PIND.2;
     for (tout = 1400; tout > 0; tout--)
        if (pin != PIND.2) break;
     if (tout == 0) {GIMSK = 0x40;   //timeout
                     EIFR = 0xC0; 
                     return;};
     _tmp = _tmp << 1;
     if (!PIND.2) _tmp++;
     };      
 _cmd = _tmp & 0x003F;    

  if ((_cmd & 0x0F) == 1) hour++; //1            slow
  if ((_cmd & 0x0F) == 2) min++;  //2            fast
  if ((_cmd & 0x0F) == 3) sec=0;  //3
  if ((_cmd & 0x0F) == 4)                      //fast
  {//4
   day++;
   day_of_week++;
   };      
  if ((_cmd & 0x0F) == 5) day = day + 31; //5       slow
  if ((_cmd & 0x0F) == 6) year++; //6             fast
  if ((_cmd & 0x0F) == 7) day--;  //7     
  if ((_cmd & 0x0F) == 8)
  {//8
   if (day>31) day=day-31;
   };
  if ((_cmd & 0x0F) == 9)
  {//9
   if (year>2000) year--;
   };  
 _cmd = 0;   
 EIFR  = 0xC0;   
 GIMSK = 0xC0;
}      

//**************************************************
// Timer 1 output compare interrupt service routine
//**************************************************
interrupt [TIM1_COMPA] void timer1_comp_isr(void)
{
// Place your code here
unsigned char vis = 0;

ms = ms + 200;
if (ms == 1000)
   {ms = 0;
    sec++;
    EIFR  = 0xC0;
    GIMSK = 0xC0;};
if (sec >= 60)
   {sec = 0;
    min++;};
if (min >= 60)
   {min = 0;
    hour++;};
if (hour >= 24)
   {hour = 0;
    day++;
    day_of_week++;};
vis = 0;    
if ((year-2000)/4*4 == (year-2000)) vis = 1;
if (day == 366+vis)
   {day = 1;
    year++;};   

month = 1;                 
day_of_month = day; 
if ((day_of_month > 59) & (vis)) day_of_month--;
while (day_of_month > max_days[month])
{day_of_month -= max_days[month];
 month++;
 };

if (day_of_week == 7) day_of_week = 1;                         
}

void main(void)
{
PORTB=0x00;
DDRB=0xFF;
PORTD=0x04;
DDRD=0x00;
TCCR1A=0x00;
TCCR1B=0x0B;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x92;
OCR1AL=0x7C;
GIMSK=0xC0;
MCUCR=0x0D;
EIFR=0xC0;
TIMSK=0x40;
TCCR0B=0x04;
TCNT0=0x00;
ACSR=0x80;
ms    = 0;
sec   = 0;
min   = 0;
hour  = 0;
day   = 1;
month = 1;
year  = 2000;
day_of_week = 6; 
day_of_month = 1;
tmr_cnt = 0;
mode = 0;
#asm("sei")

while (1)
      { 
      };
}